package com.yanfan.zutai.aop;


import com.yanfan.common.core.domain.model.LoginUser;
import com.yanfan.common.utils.SecurityUtils;
import com.yanfan.zutai.service.BCommonService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.UUID;

/**
 * 公共字段切面
 *
 * @author cl
 * @date 2020-11-20
 */
@Aspect  // 使用@Aspect注解声明一个切面
@Component
public class SysInitDataAspect {
    @Autowired
    private BCommonService bCommonService;

    /**
     * 这里我们使用注解的形式
     * 当然，我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
     * 切点表达式:   execution(...)
     */
    @Pointcut("@annotation(SysInitData)")
    public void logPointCut() {
    }

    /**
     * 环绕通知 @Around  ， 当然也可以使用 @Before (前置通知)  @After (后置通知)
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Before("logPointCut()")
    public Object around(JoinPoint point) throws Throwable {
        Object result = point.getArgs();
        try {
            initData(point);
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 保存日志
     *
     * @param joinPoint
     */
    private Object initData(JoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SysInitData sysLog = method.getAnnotation(SysInitData.class);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (sysLog != null) {
            // 请求的 类名、方法名
//            String className = joinPoint.getTarget().getClass().getSuperclass().getName();
//            String methodName = signature.getName();
            // 请求的参数
            Object[] args = joinPoint.getArgs();
            Object object = args[0];
            if (object != null) {
                Class objectClass = object.getClass().getSuperclass();
                Field[] fs = objectClass.getDeclaredFields();
                for (Field f : fs) {
                    if ("createBy".equals(f.getName())) {
                        /*
                         * 填充字段 orgId 有则取，没有则塞
                         * Method method=null;
                         */
                        try {
                            Method getOrgIdMethod = objectClass.getDeclaredMethod("getCreateBy");
                            Object o = getOrgIdMethod.invoke(object);
                            if (o == null) {
                                Method setOrgIdMethod = objectClass.getDeclaredMethod("setCreateBy", String.class);
                                setOrgIdMethod.invoke(object, loginUser.getUsername());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    if ("createTime".equals(f.getName())) {
                        /*
                         * 填充字段 orgId 有则取，没有则塞
                         * Method method=null;
                         */
                        try {
                            Method getOrgIdMethod = objectClass.getDeclaredMethod("getCreateTime");
                            Object o = getOrgIdMethod.invoke(object);
                            if (o == null) {
                                Method setOrgIdMethod = objectClass.getDeclaredMethod("setCreateTime", Date.class);
                                setOrgIdMethod.invoke(object, new Date());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    if ("updateTime".equals(f.getName())) {
                        /*
                         * 填充字段 orgId 有则取，没有则塞
                         * Method method=null;
                         */
                        try {
                            Method getOrgIdMethod = objectClass.getDeclaredMethod("getUpdateTime");
                            Object o = getOrgIdMethod.invoke(object);
                            Method setOrgIdMethod = objectClass.getDeclaredMethod("setUpdateTime", Date.class);
                            setOrgIdMethod.invoke(object, new Date());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    if ("updateBy".equals(f.getName())) {
                        try {
                            Method getOrgIdMethod = objectClass.getDeclaredMethod("getUpdateBy");
                            Object o = getOrgIdMethod.invoke(object);
                            Method setOrgIdMethod = objectClass.getDeclaredMethod("setUpdateBy", String.class);
                            setOrgIdMethod.invoke(object, loginUser.getUsername());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    if ("deptIdStrs".equals(f.getName())) {
                        try {

                            Method getOrgIdMethod = objectClass.getDeclaredMethod("getDeptIdStrs");
                            Object o = getOrgIdMethod.invoke(object);
                            if (o == null) {
                                String deptIds = "," + loginUser.getUser().getDept().getAncestors() + "," + loginUser
                                        .getUser()
                                        .getDeptId() + ",";
                                Method setOrgIdMethod = objectClass.getDeclaredMethod("setDeptIdStrs", String.class);
                                setOrgIdMethod.invoke(object, deptIds);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    if ("guid".equals(f.getName())) {
                        try {
                            Method getOrgIdMethod = objectClass.getDeclaredMethod("getGuid");
                            Object o = getOrgIdMethod.invoke(object);
                            if (o == null) {
                                Method setOrgIdMethod = objectClass.getDeclaredMethod("setGuid", String.class);
                                setOrgIdMethod.invoke(object, UUID.randomUUID().toString());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return joinPoint.getArgs();
    }
}
